package com.j4dream.ldap;

import org.springframework.ldap.core.DirContextOperations;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.ldap.authentication.LdapAuthenticator;

public class LdapAuthenticationProvider implements AuthenticationProvider {

	/** LdapAuthenticator */
	private LdapAuthenticator authenticator;
	/** 是否使用 LDAP 验证用户. */
	private boolean authenticateByLdap;

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		// TODO Auto-generated method stub
		final UsernamePasswordAuthenticationToken userToken = (UsernamePasswordAuthenticationToken) authentication;

		// 这个 username 是以 username;groupId 格式组合.
		String username = userToken.getName();
		String password = (String) authentication.getCredentials();
		String groupId = null;

		// 先从数据库获取用户.
		if ("j4dream".equals(username)) {
			throw new UsernameNotFoundException("user name not found");
		}

		if (authenticateByLdap) {
			// LDAP 验证.
			doLdapAuthentication(userToken);
		} else {
			// 数据库验证.
			String databasePassword = "12345678";
			if (!password.equals(databasePassword)) {
				throw new BadCredentialsException("incorrect password");
			}
		}

		return createSuccessfulAuthentication(userToken, username, groupId);
	}

	@Override
	public boolean supports(Class<?> authentication) {
		// TODO Auto-generated method stub
		return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
	}

	public void setAuthenticateByLdap(boolean authenticateByLdap) {
		this.authenticateByLdap = authenticateByLdap;
	}

	protected DirContextOperations doLdapAuthentication(UsernamePasswordAuthenticationToken authentication) {
		try {
			return authenticator.authenticate(authentication);
		} catch (Exception e) {
			throw new BadCredentialsException("login.error.ldap.authenticateFail", e);
		}
	}

	private Authentication createSuccessfulAuthentication(UsernamePasswordAuthenticationToken authentication, String user, String groupId) {
		Object password = authentication.getCredentials();
		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, password);
		token.setDetails("token details");
		return token;
	}
}
